package day11.homework;

import java.util.Random;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public
class Demo {
    static int index;
    public static
    void main(String[] args) {
          demo3();
    }

    //a.使用公平锁ReentrantLock实现3个线程交替打印1-100的数字，保证每个线程获取锁的机会均等
    public static void demo(){
        ReentrantLock lock=new ReentrantLock(true);
        for (int i=1;i<4;i++){
            new Thread(()->{
                while (index<100){
                    lock.lock();
                    if (index!=100) {
                        index++;
                        System.out.println(Thread.currentThread().getName()+"输出："+index);
                    }
                    lock.unlock();
                }
            },"线程"+i).start();
        }
    }
    //b.使用公平锁ReentrantLock实现一个线程安全的计数器，多个线程同时递增计数，最后输出正确结果
    public static void demo2(){
        ReentrantLock lock1=new ReentrantLock(true);
        for (int i=1;i<10;i++){
            new Thread(()->{
                while (true){
                    lock1.lock();
                    System.out.println(Thread.currentThread().getName()+"打印："+index);
                    index++;
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    lock1.unlock();
                }
            },"线程"+i).start();
        }
    }
    //a.银行账户余额查询与转账,使用ReentrantReadWriteLock实现银行账户系统，支持并发余额查询但互斥转账操作  (提示: 提供三个方法 查询(读锁)  存款(写锁)  取款(写锁))
    public static void demo3(){
        Account a=new Account();
        for (int i=1;i<3;i++){
            new Thread(()->{
                while (true) {
                    int x=new Random().nextInt(4);
                    switch (x){
                        case 1:a.query();
                        case 2:a.storage();
                        case 3:a.withdrawal();
                    }
                }
            },"线程"+i).start();
        }
    }
    //通过Lock锁编写三个线程 让其出现死锁的案例,  提示: 添加3个对象  每个线程 分别锁两个对象 让其构成一个循环链  相互等待  可以参考 课上的案例
    public static void demo4(){
        String s1="java";
        String s2="python";
        String s3="c++";
        new Thread(()->{
            synchronized (s1){
                System.out.println(Thread.currentThread().getName()+"获取s1锁");
                synchronized (s2){
                    System.out.println(Thread.currentThread().getName()+"获取s1,s2锁");
                }
                System.out.println(Thread.currentThread().getName()+"释放s2锁");
            }
            System.out.println(Thread.currentThread().getName()+"释放s1,s2锁");
        },"线程1").start();
        new Thread(()->{
            synchronized (s2){
                System.out.println(Thread.currentThread().getName()+"获取s2锁");
                synchronized (s3){
                    System.out.println(Thread.currentThread().getName()+"获取s2,s3锁");
                }
                System.out.println(Thread.currentThread().getName()+"释放s3锁");
            }
            System.out.println(Thread.currentThread().getName()+"释放s2,s3锁");
        },"线程2").start();
        new Thread(()->{
            synchronized (s3){
                System.out.println(Thread.currentThread().getName()+"获取s3锁");
                synchronized (s1){
                    System.out.println(Thread.currentThread().getName()+"获取s1,s3锁");
                }
                System.out.println(Thread.currentThread().getName()+"释放s3锁");
            }
            System.out.println(Thread.currentThread().getName()+"释放s1,s3锁");
        },"线程3").start();
    }
}
class Account{
    static int deposit=1000;
    ReentrantReadWriteLock rwl=new ReentrantReadWriteLock();
    Random r=new Random();

    public void query(){
        try {
        rwl.readLock().lock();
        System.out.println(Thread.currentThread().getName()+" 查看当前余额为："+deposit);
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            rwl.readLock().unlock();
        }
    }
    public void storage(){
        try {
            rwl.writeLock().lock();
            int i=(r.nextInt(10)+1)*100;
            deposit+=i;
            System.out.println(Thread.currentThread().getName()+" 存入："+i+",余额："+deposit);
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            rwl.writeLock().unlock();
        }
    }
    public void withdrawal(){
        try {
            rwl.writeLock().lock();
            int i=(r.nextInt(10)+1)*100;
            if(deposit>=i){
                deposit-=i;
                System.out.println(Thread.currentThread().getName()+" 取款："+i+",余额："+deposit);
            }else System.out.println(Thread.currentThread().getName()+" 取款："+i+",余额："+deposit+",余额不足");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            rwl.writeLock().unlock();
        }
    }

}
